﻿using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections.Generic;
using System;


namespace Nirvana
{
    /// <summary>
    /// UI滑动磁吸式,需要在ScrollRect物体下建立一个viewport物体，这个物体的width必须和UI组中的CellSize一样。不然磁吸会歪
    /// </summary>
    [RequireComponent(typeof(ScrollRect))]
    public class UICenterOnChild : MonoBehaviour, IBeginDragHandler, IEndDragHandler
    {
        [Min(0), Tooltip("从第几页开始")]
        public int startPage;
        [Min(0), Tooltip("自动归为的速度")]
        public float scrollSpeed = 8f;
        [Tooltip("最大页面偏移,比如最大可移动页面为3，偏移-1后，则是3 - 1 = 2")]
        public int maxPageOffset;

        [SerializeField, Tooltip("UI组")]
        private Transform UIGrid;

        private ScrollRect scrollRect;
        private float[] pageArray;
        private float targetPagePosition = 0f;
        private bool isDrag = false;
        private int pageCount;
        private int currentPage = 0;
        private List<Transform> items = new List<Transform>();
        private Action<int> Event_Alfine;

        void Awake()
        {
            scrollRect = GetComponent<ScrollRect>();
        }

        void Start()
        {
            InitPageArray();
            InvokeAlfine();
            if (scrollRect.horizontal)
            {
                scrollRect.horizontalNormalizedPosition = targetPagePosition;
            }
            else if (scrollRect.vertical)
            {
                scrollRect.verticalNormalizedPosition = targetPagePosition;
            }
        }

        /// <summary>
        /// 初始化获取元素总个数
        /// </summary>
        void InitPageArray()
        {
            items.Clear();
            if (UIGrid == null) return;

            foreach (Transform item in UIGrid)
            {
                if (item.gameObject.activeSelf && !items.Contains(item))
                {
                    items.Add(item);
                }
            }
            pageCount = items.Count;
            pageArray = new float[pageCount];
            for (int i = 0; i < pageCount; i++)
            {
                pageArray[i] = (1f / (pageCount - 1)) * i;
            }

            if (pageArray.Length > 0 && pageArray.Length > startPage)
            {
                currentPage = startPage;
                targetPagePosition = pageArray[currentPage];
            }
        }
        /// <summary>
        /// 刷新页数
        /// </summary>
        /// <param name="pageCount"></param>
        public void UpdatePageArray(int pageCount)
        {
            items.Clear();

            this.pageCount = pageCount;
            pageArray = new float[pageCount];
            for (int i = 0; i < pageCount; i++)
            {
                pageArray[i] = (1f / (pageCount - 1)) * i;
            }

            if (pageArray.Length > 0 && pageArray.Length > startPage)
            {
                currentPage = startPage;
                targetPagePosition = pageArray[currentPage];
            }
        }

        // Update is called once per frame
        void Update()
        {
            if (!isDrag)
            {
                if (scrollRect.horizontal)
                {
                    scrollRect.horizontalNormalizedPosition = Mathf.Lerp(scrollRect.horizontalNormalizedPosition, targetPagePosition, scrollSpeed * Time.deltaTime);
                }
                else if (scrollRect.vertical)
                {
                    scrollRect.verticalNormalizedPosition = Mathf.Lerp(scrollRect.verticalNormalizedPosition, targetPagePosition, scrollSpeed * Time.deltaTime);
                }
            }
        }

        public void OnBeginDrag(PointerEventData eventData)
        {
            isDrag = true;
        }

  
        public void OnEndDrag(PointerEventData eventData)
        {
            isDrag = false;
            float pos = scrollRect.horizontal ? scrollRect.horizontalNormalizedPosition : scrollRect.verticalNormalizedPosition;
            int index = 0;
            float offset = Math.Abs(pageArray[index] - pos);
            for (int i = 1; i < pageArray.Length; i++)
            {
                float _offset = Math.Abs(pageArray[i] - pos);
                if (_offset < offset)
                {
                    index = i;
                    offset = _offset;
                }
            }
            if (InRange(index))
            {
                targetPagePosition = pageArray[index];
                currentPage = index;
                InvokeAlfine();
            }
        }

        /// <summary>
        /// 向左移动一个元素
        /// </summary>
        public void ToLeft()
        {
            int nextStep = currentPage - 1;
            if (InRange(nextStep))
            {
                currentPage--;
                targetPagePosition = pageArray[currentPage];
                InvokeAlfine();
            }
        }

        /// <summary>
        /// 向右移动一个元素
        /// </summary>
        public void ToRight()
        {
            int nextStep = currentPage + 1;
            if (InRange(nextStep))
            {
                currentPage++;
                targetPagePosition = pageArray[currentPage];
                InvokeAlfine();
            }
        }

        public bool InRange(int index)
        {
            return index >= startPage && index <= pageCount - 1 + maxPageOffset;
        }

        /// <summary>
        /// 通知是否是最后一页或第一页
        /// </summary>
        public void InvokeAlfine()
        {
            if (currentPage == startPage)
            {
                Event_Alfine?.Invoke(0);
            }
            else if (currentPage == pageCount - 1 + maxPageOffset)
            {
                Event_Alfine?.Invoke(1);
            }
            else
            {
                Event_Alfine?.Invoke(2);
            }
        }

        /// <summary>
        /// 获取当前页码
        /// </summary>
        /// <returns></returns>
        public int GetCurrentPageIndex()
        {
            return currentPage;
        }
        /// <summary>
        /// 设置当前页码
        /// </summary>
        /// <param name="index"></param>
        public void SetCurrentPageIndex(int index, bool hasAni = true)
        {
            currentPage = index;
            targetPagePosition = pageArray[currentPage];
            InvokeAlfine();
            if (!hasAni)
            {
                if (scrollRect.horizontal)
                {
                    scrollRect.horizontalNormalizedPosition = targetPagePosition;
                }
                else if (scrollRect.vertical)
                {
                    scrollRect.verticalNormalizedPosition = targetPagePosition;
                }
            }
        }
        /// <summary>
        /// 获取总页数
        /// </summary>
        /// <returns></returns>
        public int GetTotalPages()
        {
            return pageCount;
        }

        /// <summary>
        /// 新增了元素后，方便刷新
        /// </summary>
        public void Refresh()
        {
            InitPageArray();
        }

        public void AddListener_Alfine(Action<int> callback)
        {
            Event_Alfine += callback;
        }

        public void RemoveListener_Alfine(Action<int> callback)
        {
            Event_Alfine -= callback;
        }
    }

}
